/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "ui时间轴.h"

#include "动作/非线性动画条.h"
#include "UI/UI.h"



static bool	g开始移动视口 = false;
static bool	g开始移动帧 = false;




float32 f_时间线_时间转坐标(float32 时间, float32 一帧间隔, C_Widget* self) {
	float32 c = 时间;
	c *= 一帧间隔;
	c *= self->m_扩展视口属性->m_比例.x;
	c += self->m_扩展视口属性->m_中心.x;
	return c;
}

Inline float32 f_时间线_每帧转绘制大小(int32 帧数量, S_时间线* 时间线, C_Widget* self) {
	return 帧数量 / 1000.0 * 时间线->m_时间线缩放 * self->m_扩展视口属性->m_比例.x;
}

Inline vec2 f_时间线_刻度线起点和宽度(S_时间线* 时间线, C_Widget* self, float32 宽度, int32& 起始刻度) {
	float32 c = 时间线->m_时间线缩放 * self->m_扩展视口属性->m_比例.x;
	c *= 宽度;

	if (self->m_扩展视口属性->m_中心.x >= 0) {
		起始刻度 = 0;
	}
	else {
		起始刻度 = self->m_扩展视口属性->m_中心.x / c;
	}
	
	return { self->m_扩展视口属性->m_中心.x + 起始刻度 * c, c };
}




static void f_update时间线绘制(C_Widget* self, C_时间轴* box) {
	
	float32 t = f_widget_从鼠标位置计算时间帧(self, box->m_尺线绘制间隔);
	box->m_时间线属性->m_时间 = t;

	//float32 时间帧位置 = 当前帧 * S_时间轴帧绘制信息::g时间区间缩放 * self->m_扩展视口属性->m_比例.x;
	//时间帧位置 += self->m_扩展视口属性->m_中心.x;
	box->m_更新绘制属性 = true;
	return;
}

static E_事件是否传递 f_时间轴页面鼠标点击(C_Widget* self, const E_鼠标按钮& 按钮) {
	C_时间轴& box = *static_cast<C_时间轴*>(self);

	f_update时间线绘制(self, &box);

	return E_事件是否传递::e_事件传递_终止;
}

static E_事件是否传递 f_时间轴页面鼠标按下(C_Widget* self, const E_鼠标按钮& 按钮) {

	if (按钮 == E_鼠标按钮::e_鼠标左键) {
		g开始移动帧 = true;
	}
	else if (按钮 == E_鼠标按钮::e_鼠标中键) {
		g开始移动视口 = true;
	}

	return E_事件是否传递::e_事件传递_终止;
}

static E_事件是否传递 f_时间轴页面鼠标放开(C_Widget* self, const E_鼠标按钮& 按钮) {
	C_时间轴* box = dynamic_cast<C_时间轴*>(self);

	if (按钮 == E_鼠标按钮::e_鼠标左键) {
		//f_update时间线绘制(self, box);
	}
	else if (按钮 == E_鼠标按钮::e_鼠标中键) {
		g开始移动视口 = false;
	}

	g开始移动帧 = false;
	return E_事件是否传递::e_事件传递_终止;
}

static E_事件是否传递 f_时间轴页面鼠标位置改变(C_Widget* self, const ivec4& mouse) {
	C_时间轴* box = dynamic_cast<C_时间轴*>(self);

	vec2 globalLoc{ float32(mouse.x), float32(mouse.y) };
	static vec2 absLoc = globalLoc;
	if (g开始移动视口) {
		
		absLoc = globalLoc - absLoc;
		self->m_扩展视口属性->m_中心 += absLoc;
		
		f_Widget_应用视口移动(self);
	}

	//f_update时间线绘制(self, box);
	absLoc = globalLoc;

	return E_事件是否传递::e_事件传递_终止;
}

static E_事件是否传递 f_时间轴页面_准备拖动(C_Widget* self, const S_鼠标& 鼠标, S_拖放数据& data) {
	data.m_Type = E_自定义拖放数据类型::e_拖放_时间线;

	if (鼠标.rgbButtons[E_鼠标按钮::e_鼠标左键]) {
		g开始移动帧 = true;
	} 
	else if (鼠标.rgbButtons[E_鼠标按钮::e_鼠标中键]) {
		g开始移动视口 = true;
	}
	return E_事件是否传递::e_事件传递_继续;
}

static E_事件是否传递 f_时间轴页面_手柄拖动(C_Widget* self, const S_鼠标& 鼠标, S_拖放数据& data) {
	if(data.m_Type != E_自定义拖放数据类型::e_拖放_时间线) return E_事件是否传递::e_事件传递_继续;

	C_时间轴* view = dynamic_cast<C_时间轴*>(self);

	//vec2 globalLoc = 鼠标.lPos;
	//static vec2 absLoc = globalLoc;
	//if (g开始移动视口) {
	//	C_Widget* view = f_ui_get滚动框视口(self);
	//
	//	absLoc = globalLoc - absLoc;
	//	self->m_扩展视口属性->m_中心 += absLoc;
	//
	//	f_Widget_应用视口移动(self);
	//}
	//absLoc = globalLoc;
	//self->m_更新绘制属性 = true;

	if (g开始移动帧) {
		//f_时间轴页面工作区_拖拽时间帧(self, 0);
		f_update时间线绘制(self, view);
	}
	
	return E_事件是否传递::e_事件传递_继续;
}

static bool f_时间轴页面_结束拖放(C_Widget* self, C_Widget* 拾取的部件, S_拖放数据& data) {

	C_时间轴* view = dynamic_cast<C_时间轴*>(self);

	if (g开始移动帧) {
		//f_update时间线绘制(self, view);
		g开始移动帧 = false;
	}
	if (g开始移动视口) {
		g开始移动视口 = false;
	}
	return true;
}





static void f_时间轴布局(C_Widget* self, C_Widget** w, uint32 num) {
	C_时间轴& box = *static_cast<C_时间轴*>(self);

	//f_Widget_保持偏移比例(self, E_方向位域::e_横向位域);

	w[0]->f_setPos({ 0, self->m_Size.y - 24 });
	w[0]->f_setSize({ self->m_Size.x, 24 });
}


static void f_draw时间轴(C_Widget* self, S_2D画布* 画布) {
	C_时间轴& box = *static_cast<C_时间轴*>(self);

	box.m_背景 = f_vg_genConvex(self->m_UIctx->m_Ctx, *画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal);
	box.m_时间线 = f_vg_genLine(self->m_UIctx->m_Ctx, *画布, E_图层混合模式::e_Normal, E_线类型::e_线段);
	box.m_刻度数值 = f_vg_genString((*self), *画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal, u"雅黑");
	

	box.m_工具栏 = f_vg_genConvex(self->m_UIctx->m_Ctx, *画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal);
}

static void f_set时间轴变换(C_Widget* self) {
	C_时间轴& box = *static_cast<C_时间轴*>(self);
	//f_vg_tranform(self->m_画布, { self->m_扩展视口属性->m_中心.x, 0 }, self->m_扩展视口属性->m_比例, {});
	f_vg_tranform(self->m_画布, { 0, 0 });
	
	
	
	//f_vg_lineText_begin(self->m_画布, box.m_刻度数值);

	std::vector<S_GPU内存块*> 缓存条形状(2);
	std::vector<S_2DConvexRect> 形状(2);

	缓存条形状[0] = &S_2D画布::g预设_矩形;
	缓存条形状[1] = &S_2D画布::g预设_矩形;
	//形状[0].offset = {};
	//形状[0].size = self->m_Size;
	形状[0].radius = {4,4};
	形状[0].AA_type.x = f_PackData4X8({ 40,40,40,255 });
	形状[0].AA_type.y = 0;

	//形状[1].offset = { box.m_时间线属性->m_区间.x * box.m_时间线属性->m_时间线缩放, 0 };
	//形状[1].size = { box.m_时间线属性->m_区间.y * box.m_时间线属性->m_时间线缩放, self->m_Size.y};
	形状[1].radius = {4,4};
	形状[1].AA_type.x = f_PackData4X8({ 60,60,60,255 });
	形状[1].AA_type.y = 0;

	//形状[1].offset.x += self->m_扩展视口属性->m_中心.x;

	f_vg_drawConvex(*box.m_背景, 2, 缓存条形状.data(), 形状.data());



	int32 刻度起点 = 0;
	vec2 刻度线起点和宽度 = f_时间线_刻度线起点和宽度(box.m_时间线属性, self, box.m_尺线绘制间隔, 刻度起点);
	float32 步进 = mod(self->m_扩展视口属性->m_中心.x, 刻度线起点和宽度.y * 4);

	S_2DConvexRect 刻度线属性;
	//刻度线属性.offset = { 步进, 0 };
	//刻度线属性.size = self->m_Size;
	刻度线属性.radius = { 1, 1 };
	刻度线属性.AA_type = { f_PackData4X8({ 50,50,50,255 }), 0 };
	//f_vg_setTickMark(self->m_画布, box.m_刻度线, 刻度线属性, 刻度线起点和宽度.y, 2);




	uint32 刻度值数量 = self->m_Size.x / (刻度线起点和宽度.y) + 1;
	std::vector<vec2> 刻度左边(刻度值数量);
	std::vector<int32> 刻度(刻度值数量);
	for (uint32 i = 0; i < 刻度值数量; ++i) {
		刻度左边[i] = { self->m_扩展视口属性->m_中心.x + i * 刻度线起点和宽度.y * 4, 2 };
		刻度[i] = i * 10;
	}
	//f_vg_setMeasure(self->m_画布, box.m_刻度数值, S_UI主题::uic_文字颜色, 刻度值数量, 刻度左边.data(), 刻度.data());


	box.m_时间线属性->m_时间线坐标 = f_时间线_时间转坐标(box.m_时间线属性->m_时间, box.m_时间线属性->m_时间线缩放, self);
	vec2 point[2] = { {box.m_时间线属性->m_时间线坐标, 0}, {box.m_时间线属性->m_时间线坐标, self->m_Size.y} };
	//f_vg_setLine(self->m_画布, box.m_时间线, 2, point, S_RGBA8UI{50, 250, 250, 255});


	
	//刻度线属性.offset = box.m_工具条->m_Pos;
	//刻度线属性.size = box.m_工具条->m_Size;
	刻度线属性.radius = { 1, 1 };
	刻度线属性.AA_type = { f_PackData4X8({ 50,50,50,255 }), 0 };
	S_GPU内存块* 元素 = &S_2D画布::g预设_矩形;
	f_vg_drawConvex(*box.m_工具栏, 1, &元素, &刻度线属性);

	
	return;
}



C_时间轴::C_时间轴(S_UI渲染环境& ctx) : C_Widget(&ctx) {
	m_Type = E_WidgetType::t_时间视口;

	mf_布局 = f_时间轴布局;
	mf_绘制 = f_draw时间轴;
	mf_变换 = f_set时间轴变换;


	mf_鼠标点击 = f_时间轴页面鼠标点击;
	mf_鼠标按键按下 = f_时间轴页面鼠标按下;
	mf_鼠标按键放开 = f_时间轴页面鼠标放开;
	mf_鼠标移动 = f_时间轴页面鼠标位置改变;

	mf_开始拖拽 = f_时间轴页面_准备拖动;
	mf_拖拽 = f_时间轴页面_手柄拖动;
	mf_结束拖拽 = f_时间轴页面_结束拖放;



	f_widget_开启视口属性(this);
	m_扩展视口属性->m_大小 = { 1024, 256 };
	m_扩展视口属性->m_比例.x = 0.1;
	m_尺线绘制间隔 = 10;


	m_工具条 = new C_Widget;
	m_工具条->mf_布局 = f_ui_Layout_工具条;
	m_工具条->m_布局方式 = E_布局方式::e_HBOX布局;
	f_添加子组件(m_工具条);

}

C_时间轴::~C_时间轴() {
	
}


C_Widget* f_ui_创建时间轴(S_UI渲染环境& ctx, S_时间线* 时间线) {
	C_时间轴* box = new C_时间轴(ctx);

	if (!时间线) {
		时间线 = new S_时间线;
	}
	box->m_时间线属性 = 时间线;
	return box;
}

void f_ui_构建时间轴工具条(C_Widget* self, const std::vector<C_Widget*>& 工具条组件) {
	C_时间轴& box = *static_cast<C_时间轴*>(self);

	box.m_工具条->m_子组件 = 工具条组件;

	for (auto& e : box.m_工具条->m_子组件) {
		e->m_父部件 = box.m_工具条;
	}
}






void f_ui_更新轨道视口焦点(C_Widget* self) {
	C_轨道视口& box = *static_cast<C_轨道视口*>(self);

	if (box.mui_当前焦点项) {
		auto e = box.mui_轨道属性栏->f_get更新组件();
		
		float32 步进 = box.m_当前轨道ID * box.m_轨道高度 + box.m_扩展视口属性->m_中心.y;

		S_2DConvexRect rect;
		//rect.offset = { 0, 步进 };
		//rect.size = { box.m_Size.x, box.mui_当前焦点项->m_Size.y };
		rect.radius = { 4,4 };
		rect.AA_type = { f_PackData4X8({20,20,20,20}), 0 };

		S_GPU内存块* 块 = &S_2D画布::g预设_圆角矩形;
		//f_vg_setElementRect(*box.m_高亮, 1, &块, &rect);
	}
	
	box.m_更新绘制属性 = true;
}


static E_事件是否传递 on_轨道视口_轨道项鼠标点击(C_Widget* self, const E_鼠标按钮& 按钮) {
	C_轨道视口& box = *static_cast<C_轨道视口*>(self);

	self->m_颜色A = S_UI主题::uic_焦点色;
	return E_事件是否传递::e_事件传递_终止;
}

static E_事件是否传递 on_轨道视口_轨道项鼠标进入(C_Widget* self, const S_鼠标& 鼠标) {
	C_轨道视口& box = *static_cast<C_轨道视口*>(self->m_父部件->m_父部件);

	float32 差 = self->m_Pos.y - box.m_扩展视口属性->m_中心.y;
	box.m_当前轨道ID = 差 / box.m_轨道高度;
	box.mui_当前焦点项 = self;

	f_ui_更新轨道视口焦点(&box);
	
	return E_事件是否传递::e_事件传递_终止;
}

static void on_update轨道视口绘制(C_Widget* self, C_轨道视口* box) {

	return;
}

static E_事件是否传递 on_轨道视口鼠标点击(C_Widget* self, const E_鼠标按钮& 按钮) {
	C_轨道视口& box = *static_cast<C_轨道视口*>(self);

	float32 缩放 = self->m_扩展视口属性->m_比例.x;
	box.m_时间线属性->m_时间 = f_widget_从鼠标位置计算时间帧(self, box.m_时间线属性->m_时间线缩放);
	
	box.m_更新绘制属性 = true;
	return E_事件是否传递::e_事件传递_终止;
}

static E_事件是否传递 on_时间轴页面鼠标按下(C_Widget* self, const E_鼠标按钮& 按钮) {

	if (按钮 == E_鼠标按钮::e_鼠标左键) {
		g开始移动帧 = true;
	}
	else if (按钮 == E_鼠标按钮::e_鼠标中键) {
		g开始移动视口 = true;
	}

	return E_事件是否传递::e_事件传递_终止;
}

static E_事件是否传递 on_轨道视口鼠标放开(C_Widget* self, const E_鼠标按钮& 按钮) {
	C_轨道视口& box = *dynamic_cast<C_轨道视口*>(self);

	if (按钮 == E_鼠标按钮::e_鼠标左键) {
		on_update轨道视口绘制(self, &box);
	}
	else if (按钮 == E_鼠标按钮::e_鼠标中键) {
		g开始移动视口 = false;
	}

	g开始移动帧 = false;
	return E_事件是否传递::e_事件传递_终止;
}

static E_事件是否传递 on_轨道视口鼠标位置改变(C_Widget* self, const ivec4& mouse) {
	C_轨道视口& box = *dynamic_cast<C_轨道视口*>(self);

	vec2 globalLoc{ float32(mouse.x), float32(mouse.y) };
	static vec2 absLoc = globalLoc;
	if (g开始移动视口) {

		absLoc = globalLoc - absLoc;

		self->m_扩展视口属性->m_中心.x += absLoc.x;
		self->m_扩展视口属性->m_中心.y += absLoc.y;
		self->m_扩展视口属性->m_中心.y = min(self->m_扩展视口属性->m_中心.y, 0);

		f_Widget_应用视口移动(self);

		//box.m_时间线属性->m_时间 = f_widget_从鼠标位置计算时间帧(self, box.m_时间线属性->m_时间线缩放);

		if (box.mui_当前焦点项) {
			on_轨道视口_轨道项鼠标进入(box.mui_当前焦点项, {});
		}
	}

	on_update轨道视口绘制(self, &box);
	absLoc = globalLoc;

	return E_事件是否传递::e_事件传递_终止;
}

static void on_轨道视口布局(C_Widget* self, C_Widget** w, uint32 num) {
	C_轨道视口& box = *static_cast<C_轨道视口*>(self);

	//f_Widget_保持偏移比例(self, E_方向位域::e_横向位域);
	self->m_扩展视口属性->m_中心.y = min(self->m_扩展视口属性->m_中心.y, 0);

	if (box.mui_轨道属性栏) {
		
		box.mui_轨道属性栏->f_setPos({ self->m_Size.x - 300, 0 });
		box.mui_轨道属性栏->f_setSize({ 300, self->m_Size.y });
		f_widget_构建滚动行组件(box.mui_轨道属性栏, box.m_轨道高度);

		auto e = box.mui_轨道属性栏->f_get更新组件();

		f_ui_Layout_无限滚动项(e.m_W, e.m_Num, { 0, 0 }, { 300, box.m_轨道高度 }, self->m_扩展视口属性->m_中心.y);

		for (uint32 i = 0; i < e.m_Num; ++i) {
			e.m_W[i]->mf_鼠标点击 = on_轨道视口_轨道项鼠标点击;
			e.m_W[i]->mf_鼠标进入 = on_轨道视口_轨道项鼠标进入;
		}
	}
}


static void on_draw轨道视口(C_Widget* self, S_2D画布* 画布) {
	C_轨道视口& box = *static_cast<C_轨道视口*>(self);

	//box.m_背景 = f_vg_drawConvexElement(画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal);
	//box.m_刻度线 = f_vg_drawTickMark(画布, E_方向::e_纵向);
	//box.m_刻度数值 = f_vg_drawLineText(画布, S_UI主题::ui_默认字体, box.m_UIctx->m_文字字号);
	//
	//box.m_采样条 = f_vg_drawConvexElement(画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal);
	//box.m_波形 = f_vg_drawWaveform(画布);
	//
	//box.m_高亮 = f_vg_drawConvexElement(画布, E_填充模式::e_填充面, E_图层混合模式::e_Screen);
	//box.m_时间线 = f_vg_genLine(self->m_UIctx->m_Ctx, *画布, E_图层混合模式::e_Normal, E_线类型::e_线段);
	//box.m_轨道标签 = f_vg_drawLineText(画布, S_UI主题::ui_默认字体, self->m_UIctx->m_文字字号);
}

static void on_set轨道视口变换(C_Widget* self) {
	C_轨道视口& box = *static_cast<C_轨道视口*>(self);
	f_vg_tranform(self->m_画布, { 0, 0 });

	//f_vg_lineText_begin(self->m_画布, box.m_刻度数值);
	//f_vg_lineText_begin(self->m_画布, box.m_轨道标签);

	uint32 轨道数量 = self->m_Size.y / 30 + 1;
	uint32 除轨道元素数量 = 1;

	float32 缩放 = self->m_扩展视口属性->m_比例.x;
	vec2 视口移动 = self->m_扩展视口属性->m_中心;


	std::vector<S_GPU内存块*> 缓存条形状(1);
	std::vector<S_2DConvexRect> 形状(1);

	if (box.mui_轨道属性栏) {
		++除轨道元素数量;

		auto e = box.mui_轨道属性栏->f_get更新组件();
		缓存条形状.resize(除轨道元素数量 + 轨道数量);
		形状.resize(除轨道元素数量 + 轨道数量);

		int32 id = fabs(self->m_扩展视口属性->m_中心.y) / box.m_轨道高度;

		vec2 下一个坐标 = {0, self->m_扩展视口属性->m_中心.y + id * box.m_轨道高度 };
		for (uint32 i = 0; i < 轨道数量; ++i) {
			uint32 index = i + 1;
			缓存条形状[index] = &S_2D画布::g预设_矩形;
			
			//形状[index].offset = 下一个坐标;
			下一个坐标.y += box.m_轨道高度;

			//形状[index].size = { self->m_Size.x, box.m_轨道高度 };
			形状[index].radius = { 8, 8 };

			
			uint8 color = 20 + (id % 2 * 5);
			形状[index].AA_type.x = f_PackData4X8({ color,color,color,255 });
			形状[index].AA_type.y = 0;
			++id;
		}

		uint32 index = 轨道数量 + 1;

		缓存条形状[index] = &S_2D画布::g预设_圆角矩形;
		//形状[index].offset = box.mui_轨道属性栏->m_Pos;
		//形状[index].size = box.mui_轨道属性栏->m_Size;
		形状[index].radius = { 8, 8 };
		形状[index].AA_type.x = f_PackData4X8({ 40,40,40,255 });
		形状[index].AA_type.y = 0;



		if (box.m_轨道数据.m_Type == E_值类型::e_Type_轨道容器) {
			const S_轨道& 轨道数据 = f_prop_轨道(box.m_轨道数据);

			uint32 num = 轨道数据.m_轨道层.size();
			for (uint32 i = 0; i < num; ++i) {
				auto tempName = f_str_u16_to_wstring_v2(轨道数据.m_轨道层[i]->name);
				//f_vg_setLineText(self->m_画布, box.m_轨道标签, tempName, { {}, {} }, E_对齐方式::e_据中对齐, S_UI主题::uic_文字颜色);
			}
		}
	}

	缓存条形状[0] = &S_2D画布::g预设_矩形;
	//形状[0].offset = {};
	//形状[0].size = self->m_Size;
	形状[0].radius = { 4,4 };
	形状[0].AA_type.x = f_PackData4X8({ 30,30,30,255 });
	形状[0].AA_type.y = 0;
	//f_vg_setElementRect(self->m_画布, box.m_背景, 缓存条形状.size(), 缓存条形状.data(), 形状.data());



	int32 刻度起点 = 0;
	vec2 刻度线起点和宽度 = f_时间线_刻度线起点和宽度(box.m_时间线属性, self, box.m_尺线绘制间隔, 刻度起点);
	float32 步进 = mod(self->m_扩展视口属性->m_中心.x, 刻度线起点和宽度.y * 4);
	
	S_2DConvexRect 刻度线属性;
	//刻度线属性.offset = { 步进, 0 };
	//刻度线属性.size = self->m_Size;
	刻度线属性.radius = { 1, 1 };
	刻度线属性.AA_type = { f_PackData4X8({ 50,50,50,255 }), 0 };
	//f_vg_setTickMark(self->m_画布, box.m_刻度线, 刻度线属性, 刻度线起点和宽度.y, 1);


	uint32 刻度值数量 = self->m_Size.x / (刻度线起点和宽度.y) + 1;
	std::vector<vec2> 刻度左边(刻度值数量);
	std::vector<int32> 刻度(刻度值数量);
	for (uint32 i = 0; i < 刻度值数量; ++i) {
		刻度左边[i] = { self->m_扩展视口属性->m_中心.x + i * 刻度线起点和宽度.y * 4, 2 };
		刻度[i] = i * 10;
	}
	f_vg_setMeasure(self->m_画布, box.m_刻度数值, S_UI主题::uic_文字颜色, 刻度值数量, 刻度左边.data(), 刻度.data());




	if (box.m_轨道数据.m_Type == E_值类型::e_Type_轨道容器) {
		std::vector<float32*> 轨道采样数据;
		std::vector<S_Waveform> 轨道采样属性;

		形状.resize(0);
		缓存条形状.resize(0);


		const auto& 轨道 = f_prop_轨道(box.m_轨道数据);
		float32 每帧采样宽度 = f_时间线_每帧转绘制大小(1, box.m_时间线属性, self);

		uint32 层ID = 0;
		for (auto& 层 : 轨道.m_轨道层) {
			for (auto& 采样条 : 层->m_层采样条) {
				switch (采样条->m_DataType) {
					case E_值类型::e_Type_I32: {
						break;
					}
					case E_值类型::e_Type_F32_1D: {
						auto& 波形数据 = f_anim_get波形轨道采样数据(采样条);
						轨道采样数据.push_back(波形数据.data());
						break;
					}
				}


				S_2DConvexRect rect;

				switch (采样条->m_SampleType) {
					case E_采样条类型::e_smaple_波形: {
						S_Waveform wf{};
						wf.m_PassNum = 1;
						wf.m_SampleWidth = 每帧采样宽度;
						//wf.m_SampleWidth = 2;
						wf.m_SampleHigth = box.m_轨道高度 - 10;
						wf.m_SampleOffset = vec2{ 采样条->m_SampleStart * 每帧采样宽度, 层ID * box.m_轨道高度 + 5} + 视口移动;
						wf.m_SampleNum = 采样条->m_SampleLength;
						wf.m_Color = f_PackData4X8({ 60, 160, 200, 255 });

						轨道采样属性.push_back(wf);

						
						//rect.offset = wf.m_SampleOffset;
						//rect.size = { 每帧采样宽度 * wf.m_SampleNum, box.m_轨道高度 - 4 };
						rect.radius = { 4,4 };
						rect.AA_type.x = f_PackData4X8({ 100,100,100,255 });
						rect.AA_type.y = 0;
						形状.push_back(rect);
						缓存条形状.push_back(&S_2D画布::g预设_圆角矩形);
						break;
					}
					case E_采样条类型::e_smaple_线性: {
						S_2DConvexRect rect;

						//rect.offset = vec2{ 采样条->m_SampleStart * 每帧采样宽度, 层ID * box.m_轨道高度 + 2} + 视口移动;
						//rect.size = { 采样条->m_SampleLength * 每帧采样宽度, box.m_轨道高度 - 4};
						rect.radius = { 4,4 };
						rect.AA_type.x = f_PackData4X8({ 100,100,100,255 });
						rect.AA_type.y = 0;
						形状.push_back(rect);
						缓存条形状.push_back(&S_2D画布::g预设_圆角矩形);
						break;
					}
				}
			}
			++层ID;
		}
		uint32 条数量 = 轨道采样属性.size();
		f_vg_setWaveform(self->m_画布, box.m_波形, 条数量, 轨道采样属性.data(), 轨道采样数据.data());


		
		//形状.resize(条数量);
		//缓存条形状.resize(条数量);
		//for (uint32 i = 0; i < 条数量; ++i) {
		//	缓存条形状[i] = &S_2D画布::g预设_圆角矩形;
		//	形状[i].offset = 轨道采样属性[i].m_SampleOffset;
		//	形状[i].size = { 每帧采样宽度 * 轨道采样属性[i].m_SampleNum, box.m_轨道高度 };
		//	形状[i].radius = { 4,4 };
		//	形状[i].color_type.x = f_PackData4X8({ 100,100,100,255 });
		//	形状[i].color_type.y = 0;
		//}
		//f_vg_setElementRect(self->m_画布, box.m_采样条, 缓存条形状.size(), 缓存条形状.data(), 形状.data());

	}
	

	box.m_时间线属性->m_时间线坐标 = f_时间线_时间转坐标(box.m_时间线属性->m_时间, box.m_时间线属性->m_时间线缩放, self);
	vec2 point[2] = { {box.m_时间线属性->m_时间线坐标, 0}, {box.m_时间线属性->m_时间线坐标, self->m_Size.y} };
	//f_vg_setLine(self->m_画布, box.m_时间线, 2, point, S_RGBA8UI{ 50, 250, 250, 255 });

	return;
}



C_轨道视口::C_轨道视口(S_UI渲染环境& ctx) : C_Widget(&ctx) {
	m_Type = E_WidgetType::t_轨道视口;

	mf_布局 = on_轨道视口布局;
	mf_绘制 = on_draw轨道视口;
	mf_变换 = on_set轨道视口变换;


	mf_鼠标点击 = on_轨道视口鼠标点击;
	mf_鼠标按键按下 = on_时间轴页面鼠标按下;
	mf_鼠标按键放开 = on_轨道视口鼠标放开;
	mf_鼠标移动 = on_轨道视口鼠标位置改变;


	f_widget_开启视口属性(this);
	m_扩展视口属性->m_中心 = {};
	//m_时间区间缩放 = 5;
	m_尺线绘制间隔 = 10;
	m_轨道高度 = 40;
	m_轨道移动方式 = E_移动方式::e_移动方式_自由;


	mui_当前焦点项 = nullptr;
	m_当前轨道ID = 0;
	m_轨道属性编辑栏 = false;
	m_更新绘制属性 = {};
}

C_轨道视口::~C_轨道视口() {
	
}


C_Widget* f_ui_创建轨道视口(S_UI渲染环境& ctx, S_时间线* 时间线, bool 轨道添加栏) {
	C_轨道视口* box = new C_轨道视口(ctx);

	if (!时间线) {
		时间线 = new S_时间线;
	}
	box->m_时间线属性 = 时间线;

	box->m_轨道属性编辑栏 = 轨道添加栏;

	if (box->m_轨道属性编辑栏) {
		box->mui_轨道属性栏 = new C_Widget;
		box->f_添加子组件(box->mui_轨道属性栏);

		f_widget_构建滚动行组件(box->mui_轨道属性栏, box->m_轨道高度);
	}
	
	return box;
}

void f_ui_绑定轨道数据(C_Widget* self, S_Props& 轨道数据) {
	C_轨道视口& box = *dynamic_cast<C_轨道视口*>(self);

	box.m_轨道数据 = 轨道数据;
	box.m_更新绘制属性 = true;
}

void f_ui_set轨道时间(C_Widget* self, float32 时间) {
	C_轨道视口& box = *dynamic_cast<C_轨道视口*>(self);
	float32 缩放 = self->m_扩展视口属性->m_比例.x;

	box.m_时间线属性->m_时间 = 时间;
	box.m_时间线属性->m_时间线坐标 = f_时间线_时间转坐标(时间, box.m_时间线属性->m_时间线缩放, self);
	box.m_更新绘制属性 = true;
}

void f_ui_set轨道帧移动方式(C_Widget* self, E_移动方式 移动方式) {
	C_轨道视口& box = *dynamic_cast<C_轨道视口*>(self);
	box.m_轨道移动方式 = 移动方式;
}

void f_ui_移动轨道时间线到中间(C_轨道视口& box) {

	float32 帧左边 = box.m_时间线属性->m_时间 * box.m_时间线属性->m_时间线缩放 * box.m_扩展视口属性->m_比例.x;

	帧左边 = box.m_Size.x * 0.5 - 帧左边;
	box.m_扩展视口属性->m_中心.x = 帧左边;

	//box.m_时间线属性->m_时间线坐标 = f_时间线_时间转坐标(box.m_时间线属性->m_时间, box.m_时间线属性->m_时间线缩放, &box);
	//float32 帧到左边距离 = box.m_Size.x - box.m_时间线属性->m_时间线坐标;
	//box.m_扩展视口属性->m_中心.x -= 帧到左边距离;
}

void f_ui_set轨道层高度(C_Widget* self, float32 高度) {
	C_轨道视口& box = *dynamic_cast<C_轨道视口*>(self);
	box.m_轨道高度 = 高度;
}



static void on_波形框布局(C_Widget* self, C_Widget** w, uint32 num) {
	C_波形框& box = *static_cast<C_波形框*>(self);

	//f_Widget_计算视口缩放保持偏移比例(self, E_方向位域::e_横向位域);

}

static void on_draw波形框(C_Widget* self, S_2D画布* 画布) {
	C_波形框& box = *static_cast<C_波形框*>(self);

	//box.m_背景 = f_vg_drawConvexElement(画布, E_填充模式::e_填充面, E_图层混合模式::e_Normal);
	//box.m_刻度线 = f_vg_drawTickMark(画布, E_方向::e_纵向);
	box.m_波形 = f_vg_drawWaveform(画布);

}

static void on_set波形框变换(C_Widget* self) {
	C_波形框& box = *static_cast<C_波形框*>(self);
	f_vg_tranform(self->m_画布, { 0, 0 }, self->m_扩展视口属性->m_比例);

	uint32 轨道数量 = self->m_Size.y / 30 + 1;
	uint32 除轨道元素数量 = 1;

	std::vector<S_GPU内存块*> 缓存条形状(1);
	std::vector<S_2DConvexRect> 形状(1);

	缓存条形状[0] = &S_2D画布::g预设_圆角矩形;
	//形状[0].offset = {};
	//形状[0].size = self->m_Size;
	形状[0].radius = { 6, 6 };
	形状[0].AA_type.x = f_PackData4X8({ 50,50,50,255 });
	形状[0].AA_type.y = 0;
	//f_vg_setElementRect(self->m_画布, box.m_背景, 缓存条形状.size(), 缓存条形状.data(), 形状.data());


	S_2DConvexRect 刻度线属性;
	//刻度线属性.offset = { 0, 0 };
	//刻度线属性.size = self->m_Size;
	刻度线属性.radius = { 1, 1 };
	刻度线属性.AA_type = { f_PackData4X8({ 60,60,60,255 }), 0 };
	//f_vg_setTickMark(self->m_画布, box.m_刻度线, 刻度线属性, 20, 0);


	
	box.m_波形属性.m_PassNum = 1;
	box.m_波形属性.m_SampleWidth = 1.0;
	box.m_波形属性.m_SampleHigth = self->m_Size.y;
	box.m_波形属性.m_Color = { f_PackData4X8({ 60, 160, 200, 255 }) };
	f_vg_setWaveform(self->m_画布, box.m_波形, box.m_波形数据.size(), box.m_波形数据.data());
	f_vg_setWaveformRect(self->m_画布, box.m_波形, box.m_波形属性, self->m_Size.x);

	return;
}



C_波形框::C_波形框(S_UI渲染环境& ctx) : C_Widget(&ctx) {
	mf_布局 = on_波形框布局;
	mf_绘制 = on_draw波形框;
	mf_变换 = on_set波形框变换;

	//mf_鼠标点击 = on_轨道视口鼠标点击;
	//mf_鼠标按键按下 = on_时间轴页面鼠标按下;
	//mf_鼠标按键放开 = on_轨道视口鼠标放开;
	//mf_鼠标移动 = on_轨道视口鼠标位置改变;

	f_widget_开启视口属性(this);
	m_扩展视口属性->m_中心 = {};
	
	m_滚动 = true;
	m_更新绘制属性 = {};
}

C_波形框::~C_波形框() {
	
}

C_Widget* f_ui_创建波形框(S_UI渲染环境& ctx, bool 堆叠绘制, bool 滚动) {
	C_波形框* box = new C_波形框(ctx);

	box->m_堆叠绘制 = 堆叠绘制;
	box->m_滚动 = 滚动;

	return box;
}

std::vector<float32>& f_ui_get波形框波形(C_Widget* self) {
	C_波形框& box = *dynamic_cast<C_波形框*>(self);
	box.m_更新绘制属性 = true;
	return box.m_波形数据;
}

void f_ui_添加波形采样点(C_Widget* self, uint32 通道, float32 值) {
	C_波形框& box = *dynamic_cast<C_波形框*>(self);

	uint32 绘制采样数量 = box.m_Size.x / box.m_波形属性.m_SampleWidth * 2;

	if (box.m_波形数据.size() > 绘制采样数量) {
		box.m_波形数据.erase(box.m_波形数据.begin());
		box.m_波形数据.back() = 值;
	}
	else {
		box.m_波形数据.push_back(值);
	}
}


//C_Widget* f_ui_波形框绑定属性(S_UI创建环境& ctx, S_Props& 波形数据) {
//	C_波形框* box = new C_波形框(ctx);
//
//	box->m_波形数据 = 波形数据;
//
//	return box;
//}








void f_ui_移动时间线到中间(C_Widget* self) {
	switch (self->m_Type) {
		case E_WidgetType::t_时间视口: {
			break;
		}
		case E_WidgetType::t_轨道视口: {
			f_ui_移动轨道时间线到中间(*dynamic_cast<C_轨道视口*>(self));
			break;
		}
		default:
			break;
	}
}



